use std::fmt::Debug;
use std::fs;
use std::path::PathBuf;
use std::process::{Child, Command};
use std::sync::OnceLock;
use std::time::Duration;

use crate::{components, dao, runtime};
use crate::components::v2ray::config;
use crate::models::models::components::v2ray::info::ComponentV2rayState;
use crate::models::models::components::v2ray::proxy_mode::ComponentV2rayProxyMode;
use crate::models::models::components::v2ray::subscription::ComponentV2raySubscriptionLastUpdateState;
use crate::runtime::{io, os};
use crate::runtime::error::MagicBoxError;
use crate::runtime::response::Code;
use crate::runtime::result::MagicBoxResult;

static mut MANAGER: OnceLock<Manager> = OnceLock::new();

pub(crate) fn manager() -> &'static mut Manager {
    unsafe {
        MANAGER.get_or_init(|| Manager::default());

        MANAGER.get_mut().unwrap()
    }
}

#[derive(Debug)]
pub(crate) struct Manager {
    version: String,
    state: Option<ComponentV2rayState>,
    install_stage: String,
    install_percent: u64,
    command: Option<Child>,
    stopping: bool,
    updater: Option<tokio::task::JoinHandle<()>>,
}

impl Default for Manager {
    fn default() -> Self {
        Self {
            version: "-".to_string(),
            state: None,
            install_stage: "".to_string(),
            install_percent: 0,
            command: None,
            stopping: false,
            updater: None,
        }
    }
}

impl Drop for Manager {
    fn drop(&mut self) {
        let result = self.stop();
        if result.is_err() {
            log::error!("stop v2ray failed: {}", result.unwrap_err().to_string());
        }

        if self.updater.is_some() {
            self.updater.as_ref().unwrap().abort();
        }
    }
}

impl Manager {
    /// 获取v2ray安装路径
    pub(crate) fn install_path(&self) -> MagicBoxResult<PathBuf> {
        io::data_path(PathBuf::new().join("v2ray"))
    }

    /// 获取v2ray命令路径
    pub(crate) fn command_path(&self) -> MagicBoxResult<PathBuf> {
        Ok(io::data_path(PathBuf::new().join("v2ray"))?.join(match os::SYSTEM {
            "Windows" => "v2ray.exe",
            _ => "v2ray"
        }))
    }

    /// 检查v2ray是否已安装
    pub(crate) fn is_installed(&self) -> MagicBoxResult<bool> {
        let v2ray_path = self.command_path()?;

        Ok(v2ray_path.exists())
    }

    /// 更新安装进度
    pub(crate) fn installing(&mut self, state: ComponentV2rayState, stage: &str, percent: u64) {
        self.state = Some(state);
        self.install_stage = stage.to_string();
        self.install_percent = percent;
    }

    /// 卸载V2ray
    pub(crate) fn uninstall(&mut self) -> MagicBoxResult<()> {
        let v2ray_path = self.install_path()?;
        if !v2ray_path.exists() {
            return Ok(());
        }

        let result = fs::remove_dir_all(v2ray_path.as_path());
        if result.is_err() {
            let err = result.unwrap_err().to_string();
            log::error!("卸载V2ray失败: {}", err.as_str());

            return Err(MagicBoxError::new(Code::IoError, format!("卸载V2ray失败: {}", err.as_str()).as_str()));
        }

        self.state = Some(ComponentV2rayState::NotInstall);

        Ok(())
    }

    /// 获取v2ray版本
    pub(crate) fn version_name(&mut self) -> MagicBoxResult<String> {
        // 未安装、安装阶段、安装失败无法查询版本号
        if ComponentV2rayState::NotInstall == self.state()? || ComponentV2rayState::Installing == self.state()? || ComponentV2rayState::InstallFailed == self.state()? || "-" != self.version {
            return Ok(self.version.clone());
        }

        // 4版本
        {
            let command = Command::new(self.command_path()?.as_os_str()).arg("-version").output();
            log::debug!("组件-V2ray V4版本探测{:?}", command);

            if command.is_ok() {
                let output = command.unwrap();
                if output.status.success() {
                    let output = String::from_utf8(output.stdout.to_vec());
                    if output.is_err() {
                        let err = output.unwrap_err().to_string();
                        log::error!("获取v2ray -version命令输出失败: {}", err.as_str());

                        return Err(MagicBoxError::new(Code::UndefinedError, format!("获取V2ray-Core版本失败: {}", err.as_str()).as_str()));
                    }

                    let output = output.unwrap();
                    let tokens = output.split(' ').collect::<Vec<&str>>();
                    if 2 > tokens.len() {
                        log::error!("无效的v2ray -version命令输出: {}", output.as_str());

                        return Err(MagicBoxError::new(Code::UndefinedError, format!("获取V2ray-Core版本失败: {}", output.as_str()).as_str()));
                    }

                    self.version = tokens[1].to_string();

                    return Ok(self.version.clone());
                }
            }
        }

        // 5版本
        {
            let command = Command::new(self.command_path()?.as_os_str()).arg("version").output();
            log::debug!("组件-V2ray V5版本探测{:?}", command);

            if command.is_ok() {
                let output = command.unwrap();
                if !output.status.success() {
                    log::error!("获取v2ray version命令输出失败，v2ray命令异常退出: {}", output.status.to_string());

                    return Err(MagicBoxError::new(Code::UndefinedError, format!("获取V2ray-Core版本失败: {}", output.status.to_string()).as_str()));
                }

                let output = String::from_utf8(output.stdout.to_vec());
                if output.is_err() {
                    let err = output.unwrap_err().to_string();
                    log::error!("获取v2ray version命令输出失败: {}", err.as_str());

                    return Err(MagicBoxError::new(Code::UndefinedError, format!("获取V2ray-Core版本失败: {}", err.as_str()).as_str()));
                }

                let output = output.unwrap();
                let tokens = output.split(' ').collect::<Vec<&str>>();
                if 2 > tokens.len() {
                    log::error!("无效的v2ray version命令输出: {}", output.as_str());

                    return Err(MagicBoxError::new(Code::UndefinedError, format!("获取V2ray-Core版本失败: {}", output.as_str()).as_str()));
                }

                self.version = tokens[1].to_string();

                return Ok(self.version.clone());
            }
        }

        Ok(self.version.clone())
    }

    /// 获取v2ray状态
    pub(crate) fn state(&mut self) -> MagicBoxResult<ComponentV2rayState> {
        if self.state.is_none() {
            self.state = Some(if self.is_installed()? { ComponentV2rayState::NotRunning } else { ComponentV2rayState::NotInstall });
        }

        Ok(self.state.clone().unwrap())
    }

    /// 获取v2ray安装阶段
    pub(crate) fn get_install_stage(&self) -> String {
        self.install_stage.clone()
    }

    /// 获取v2ray安装进度
    pub(crate) fn get_install_percent(&self) -> u64 {
        self.install_percent
    }

    /// 启动v2ray
    pub(crate) fn start(&mut self) -> MagicBoxResult<()> {
        if ComponentV2rayState::Running == self.state()? {
            return Ok(());
        }

        // 重新生成客户端配置
        config::v4::generate_client_config()?;

        let config_path = self.install_path()?.join("local_config.json");

        let mut command = Command::new(self.command_path()?.as_os_str());
        if self.version.starts_with("4") {
            // 4版本
            command.arg("-c").arg(config_path.as_os_str());
        } else {
            // 其他版本
            command.arg("run").arg("-c").arg(config_path.as_os_str());
        }

        let result = command.spawn();
        if result.is_err() {
            let err = result.unwrap_err().to_string();
            log::error!("启动v2ray失败: {}", err.as_str());

            return Err(MagicBoxError::new(Code::UndefinedError, format!("启动v2ray失败: {}", err.as_str()).as_str()));
        }

        self.state = Some(ComponentV2rayState::Running);
        self.command.replace(result.unwrap());

        // 监控V2ray运行状态
        runtime::tokio::runtime().spawn(async {
            if manager().command.is_some() {
                let child = manager().command.as_mut().unwrap();

                let status = child.wait();
                if status.is_err() {
                    let err = status.unwrap_err().to_string();
                    log::error!("v2ray运行异常退出: {}", err.as_str());

                    manager().state = Some(ComponentV2rayState::Failed);

                    return;
                }

                let status = status.unwrap();
                if status.success() || manager().stopping {
                    manager().state = Some(ComponentV2rayState::NotRunning);

                    return;
                }

                manager().state = Some(ComponentV2rayState::Failed);
            }
        });

        // 启动服务器订阅更新线程
        if self.updater.is_none() {
            self.updater = Some(runtime::tokio::runtime().spawn(async {
                log::info!("服务器订阅更新线程已启动");

                loop {
                    // 等待到下一个十分钟
                    tokio::time::sleep(Duration::from_secs(600 - (chrono::Utc::now().timestamp() % 600) as u64)).await;

                    let subscriptions = dao::components::v2ray::subscription::get_subscription_configs();
                    if subscriptions.is_err() {
                        log::error!("查询订阅列表失败: {}", subscriptions.err().unwrap().to_string());

                        continue;
                    }

                    for subscription in subscriptions.unwrap() {
                        if !subscription.enabled || !subscription.auto_update {
                            log::info!("服务器: {} 未启用或未开启自动更新，跳过", subscription.name);

                            continue;
                        }

                        log::info!("服务器: {} 自动更新，订阅地址: {}", subscription.name, subscription.url.as_str());

                        let servers = components::v2ray::subscription::fetch_servers(subscription.url.as_str()).await;
                        if servers.is_err() {
                            log::error!("获取订阅服务器列表失败: {}", servers.err().unwrap().to_string());
                            let result = dao::components::v2ray::subscription::update_last_update_time(&subscription, chrono::Utc::now().timestamp(), ComponentV2raySubscriptionLastUpdateState::Failed);
                            if result.is_err() {
                                log::error!("更新订阅更新状态失败: {}", result.unwrap_err().to_string());
                            }

                            continue;
                        }

                        for server in servers.unwrap() {
                            let exists = dao::components::v2ray::server::get_server_with_tag(server.tag.as_str());
                            if exists.is_err() {
                                log::error!("查询服务器配置失败: {}", exists.err().unwrap().to_string());

                                continue;
                            }

                            let exists = exists.unwrap();
                            let result = dao::components::v2ray::server::save_server_config(server.clone(), exists.is_some());
                            if result.is_err() {
                                log::error!("保存服务器配置失败: {}", result.err().unwrap().to_string());

                                continue;
                            }

                            if exists.is_some() {
                                let exists = exists.unwrap();

                                // 如果当前服务器正在使用中且服务器配置已变更，重启服务
                                if exists.used && (exists.address != server.address || exists.port != server.port || exists.user_id != server.user_id || exists.websocket_setting.path != server.websocket_setting.path) {
                                    let result = manager().stop();
                                    if result.is_err() {
                                        log::error!("停止v2ray服务失败: {}", result.err().unwrap().to_string());

                                        continue;
                                    }

                                    let result = manager().start();
                                    if result.is_err() {
                                        log::error!("启动v2ray服务失败: {}", result.err().unwrap().to_string());

                                        continue;
                                    }
                                }
                            }
                        }

                        let result = dao::components::v2ray::subscription::update_last_update_time(&subscription, chrono::Utc::now().timestamp(), ComponentV2raySubscriptionLastUpdateState::Success);
                        if result.is_err() {
                            log::error!("更新订阅更新状态失败: {}", result.unwrap_err().to_string());
                        }
                    }
                }
            }));
        }

        // 设置系统代理
        let basic_setting = dao::components::v2ray::setting::get_basic_setting();
        if basic_setting.is_some() {
            let basic_setting = basic_setting.unwrap();
            if ComponentV2rayProxyMode::Router == basic_setting.proxy_mode || ComponentV2rayProxyMode::Global == basic_setting.proxy_mode {
                components::v2ray::proxy::set_system_global_proxy(&basic_setting)?;
            }
        }

        Ok(())
    }

    /// 停止v2ray
    pub(crate) fn stop(&mut self) -> MagicBoxResult<()> {
        if ComponentV2rayState::Running != self.state()? {
            return Ok(());
        }

        // 清理系统代理
        components::v2ray::proxy::clear_system_global_proxy()?;

        self.stopping = true;
        if self.command.is_some() {
            let result = self.command.as_mut().unwrap().kill();
            if result.is_err() {
                let err = result.unwrap_err().to_string();
                log::error!("停止v2ray失败: {}", err.as_str());

                return Err(MagicBoxError::new(Code::UndefinedError, format!("停止v2ray失败: {}", err.as_str()).as_str()));
            }
        }

        Ok(())
    }
}

